#ifndef __STRINGX_H__
#define __STRINGX_H__

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <memory.h>
#include <string.h>

class String
{
public:
	String() : m_iMax(0), m_iSize(0), m_pMem(0) {}
	
	String(const char* szBuf) : m_iMax(0), m_iSize(0), m_pMem(0)
	{
		int n = szBuf ? strlen(szBuf) : 0;
		if(n>0 && more(n))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize = n;
			*(m_pMem + m_iSize) = 0;
		}
	}
	
	String(const char* szBuf, int n) : m_iMax(0), m_iSize(0), m_pMem(0)
	{
		if(szBuf && n>0 && more(n))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize = n;
			*(m_pMem + m_iSize) = 0;
		}
	}
	
	String(const String& oString) : m_iMax(0), m_iSize(0), m_pMem(0)
	{
		int n = oString.m_iSize;
		if(n>0 && more(n))
		{
			memmove(m_pMem, oString.m_pMem, n);
			m_iSize = n;
			*(m_pMem + m_iSize) = 0;
		}
	}
	
	~String()
	{
		if(m_pMem)
		{
			free(m_pMem); 
			m_pMem=0; 
		}
		m_iSize = m_iMax = 0;
	}
	
	void clear()
	{
		if(m_pMem)
		{
			free(m_pMem); 
			m_pMem=0; 
		}
		m_iSize = m_iMax = 0;
	}
	
	inline int length() const {return m_iSize;}
	inline int capacity() const {return m_iMax ? m_iMax-1 : 0;}
	inline char& operator[] (int i) {return m_pMem[i];}

	inline operator char* () {return m_pMem;}
	inline const char* c_str() const {return m_iMax ? m_pMem : "";}
	
	String& append(const char* szBuf)
	{
		int n = szBuf ? strlen(szBuf) : 0;
		int m = m_iMax - m_iSize;
		if(n>0 && (n<m || more(n-m)))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize += n;
			*(m_pMem + m_iSize) = 0;
		}
		return *this;
	}
	
	String& append(const char* szBuf, int n)
	{
		int m = m_iMax - m_iSize;
		if(szBuf && n>0 && (n<m || more(n-m)))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize += n;
			*(m_pMem + m_iSize) = 0;
		}
		return *this;
	}
	
	String& append(const String& oString)
	{
		int n = oString.m_iSize;
		int m = m_iMax - m_iSize;
		if(n>0 && (n<m || more(n-m)))
		{
			memmove(m_pMem, oString.m_pMem, n);
			m_iSize += n;
			*(m_pMem + m_iSize) = 0;
		}
		return *this;
	}
	
	void format(const char* szFormat, ...)
	{
		va_list v;
		va_start(v, szFormat);
		char szBuf[1024] = "";
	#ifdef _MSC_VER
		(void) _vsnprintf(szBuf, 1024, szFormat, v);
	#elif __GNUC__
		(void) vsnprintf(szBuf, 1024, szFormat, v);
    #else 
        #error unknown platform for 'vsnprintf'.
	#endif
		(*this) = szBuf;
		va_end(v);
	}
	
	String& operator = (const char* szBuf)
	{
		m_iSize = 0;
		int n = szBuf ? strlen(szBuf) : 0;
		if(n>0 && (n<m_iMax || more(n-m_iMax)))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize = n;
			*(m_pMem + m_iSize) = 0;
		}
		return *this;
	}
	
	String& operator = (const String& oString)
	{
		if(this != &oString)
		{
			m_iSize = 0;
			int n = oString.m_iSize;
			if(n>0 && (n<m_iMax || more(n-m_iMax)))
			{
				memmove(m_pMem, oString.m_pMem, n);
				m_iSize = n;
				*(m_pMem + m_iSize) = 0;
			}
		}
		return *this;
	}

	String assign(const char* szBuf, int n)
	{
		m_iSize = 0;
		if(n>0 && (n<m_iMax || more(n-m_iMax)))
		{
			memmove(m_pMem, szBuf, n);
			m_iSize = n;
			*(m_pMem + m_iSize) = 0;
		}
		return *this;
	}
	
	int compare(const char* szBuf) const
	{
		int n = szBuf ? strlen(szBuf) : 0;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, szBuf, m) : 0;
		return c ? c : (m_iSize - n);
	}
	
	int compare(const String& oString) const
	{
		int n = oString.m_iSize;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, oString.m_pMem, m) : 0;
		return c ? c : (m_iSize - n);
	}

	bool operator < (const char* szBuf) const
	{
		int n = szBuf ? strlen(szBuf) : 0;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, szBuf, m) : 0;
		return (c ? c : (m_iSize - n)) < 0;
	}

	bool operator < (const String& oString) const
	{
		int n = oString.m_iSize;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, oString.m_pMem, m) : 0;
		return (c ? c : (m_iSize - n)) < 0;
	}

	bool operator == (const char* szBuf) const
	{
		int n = szBuf ? strlen(szBuf) : 0;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, szBuf, m) : 0;
		return (c ? c : (m_iSize - n)) == 0;
	}

	bool operator == (const String& oString) const
	{
		int n = oString.m_iSize;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, oString.m_pMem, m) : 0;
		return (c ? c : (m_iSize - n)) == 0;
	}

	bool operator != (const char* szBuf) const
	{
		int n = szBuf ? strlen(szBuf) : 0;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, szBuf, m) : 0;
		return (c ? c : (m_iSize - n)) != 0;
	}

	bool operator != (const String& oString) const
	{
		int n = oString.m_iSize;
		int m = n<m_iSize ? n : m_iSize;

		int c = m ? memcmp(m_pMem, oString.m_pMem, m) : 0;
		return (c ? c : (m_iSize - n)) != 0;
	}
	
private:
	bool more(int n)
	{
		if(m_iMax==0) n = (n<16 ? 16 : n+1);
		n = (n<m_iMax ? m_iMax+m_iMax : n+m_iMax);
		
		char* pNewMem = (char*)malloc(n);
		if(!pNewMem) return false;
		
		memmove(pNewMem, m_pMem, m_iSize);
		*(pNewMem + m_iSize) = 0;
		
		if(m_pMem) free(m_pMem);
		m_pMem = pNewMem;
		m_iMax = n;
		return true;
	}

public:
	char* m_pMem;
	int m_iMax;
	int m_iSize;
};

#endif
